package com.zone.canvas;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.zone.canvas.base.BaseActivity;
import com.zone.canvas.tools.EditingToolsAdapter;
import com.zone.canvas.tools.FileUtil;
import com.zone.canvas.tools.JsonParser;
import com.zone.canvas.tools.ToolType;
import com.zone.editor.SaveSettings;
import com.zone.editor.TextStyleBuilder;
import com.zone.editor.ViewType;
import com.zone.editor.inter.Editor;
import com.zone.editor.inter.OnEditorListener;
import com.zone.editor.photoEditor.PhotoEditorView;
import com.zone.editor.pixel.PixUtils;
import com.zone.editor.shape.ShapeBuilder;
import com.zone.editor.shape.ShapeType;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.zone.canvas.FileSaveHelper.isSdkHigherThan28;

public class EditDLPImageActivity extends BaseActivity implements OnEditorListener,
        View.OnClickListener,
        PropertiesBSFragment.Properties,
        ShapeBSFragment.Properties,
        EmojiBSFragment.EmojiListener,
        StickerBSFragment.StickerListener, EditingToolsAdapter.OnItemSelected
{

    private static final String TAG = EditDLPImageActivity.class.getSimpleName();

    Editor mEditor;
    private PhotoEditorView photoEditorView;
    private PropertiesBSFragment mPropertiesBSFragment;
    private ShapeBSFragment mShapeBSFragment;
    private ShapeBuilder mShapeBuilder;
    private EmojiBSFragment mEmojiBSFragment;
    private StickerBSFragment mStickerBSFragment;
    private TextView mTxtCurrentTool;
    private RecyclerView mRvTools;
    private final EditingToolsAdapter mEditingToolsAdapter = new EditingToolsAdapter(this);



    @Nullable
    @VisibleForTesting
    Uri mSaveImageUri;

    private FileSaveHelper mSaveFileHelper;

    private static Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        makeFullScreen();
        setContentView(R.layout.activity_edit_image_dlp);
        context = this;
        initViews();

        mPropertiesBSFragment = new PropertiesBSFragment();
        mEmojiBSFragment = new EmojiBSFragment();
        mStickerBSFragment = new StickerBSFragment();
        mShapeBSFragment = new ShapeBSFragment();
        mStickerBSFragment.setStickerListener(this);
        mEmojiBSFragment.setEmojiListener(this);
        mPropertiesBSFragment.setPropertiesChangeListener(this);
        mShapeBSFragment.setPropertiesChangeListener(this);

        LinearLayoutManager llmTools = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        mRvTools.setLayoutManager(llmTools);
        mRvTools.setAdapter(mEditingToolsAdapter);

        mEditor = new Editor.Builder(this, photoEditorView).build(); // build photo editor sdk

        mEditor.setOnEditorListener(this);

        photoEditorView.getSource().setImageResource(R.drawable.bg);

        mSaveFileHelper = new FileSaveHelper(this);

        //讯飞语音初始化
        initSpeech();
//        initSpeechLocal();
    }

    private void initViews() {
        ImageView imgUndo;
        ImageView imgRedo;
        ImageView imgSave;
        ImageView imgClose;
        photoEditorView = findViewById(R.id.pixelEditorView);
        mTxtCurrentTool = findViewById(R.id.txtCurrentTool);
        mRvTools = findViewById(R.id.rvConstraintTools);

        imgUndo = findViewById(R.id.imgUndo);
        imgUndo.setOnClickListener(this);

        imgRedo = findViewById(R.id.imgRedo);
        imgRedo.setOnClickListener(this);


        imgSave = findViewById(R.id.imgSave);
        imgSave.setOnClickListener(this);

        imgClose = findViewById(R.id.imgClose);
        imgClose.setOnClickListener(this);

        findViewById(R.id.speech).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction() == MotionEvent.ACTION_UP){
                    stop();
                }
                if(event.getAction() == MotionEvent.ACTION_DOWN){
                    start();
                }
                return true;
            }
        });
    }

    @Override
    public void onEditTextChangeListener(final View rootView, String text, int colorCode) {
        TextEditorDialogFragment textEditorDialogFragment =
                TextEditorDialogFragment.show(this, text, colorCode);
        textEditorDialogFragment.setOnTextEditorListener((inputText, newColorCode) -> {
            final TextStyleBuilder styleBuilder = new TextStyleBuilder();
            styleBuilder.withTextColor(newColorCode);
            styleBuilder.withTextFont(Typeface.createFromAsset(getAssets(), "fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf"));
            mEditor.editText(rootView, inputText, styleBuilder);
            mTxtCurrentTool.setText(R.string.label_text);
        });
    }

    @Override
    public void onAddViewListener(ViewType viewType, int numberOfAddedViews) {
        Log.d(TAG, "onAddViewListener() called with: viewType = [" + viewType + "], numberOfAddedViews = [" + numberOfAddedViews + "]");
    }

    @Override
    public void onRemoveViewListener(ViewType viewType, int numberOfAddedViews) {
        Log.d(TAG, "onRemoveViewListener() called with: viewType = [" + viewType + "], numberOfAddedViews = [" + numberOfAddedViews + "]");
    }

    @Override
    public void onStartViewChangeListener(ViewType viewType) {
        Log.d(TAG, "onStartViewChangeListener() called with: viewType = [" + viewType + "]");
    }

    @Override
    public void onStopViewChangeListener(ViewType viewType) {
        Log.d(TAG, "onStopViewChangeListener() called with: viewType = [" + viewType + "]");
    }

    @Override
    public void onTouchSourceImage(MotionEvent event) {
        Log.d(TAG, "onTouchView() called with: event = [" + event + "]");
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            case R.id.imgUndo:
                mEditor.undo();
                break;

            case R.id.imgRedo:
//                mEditor.redo();
                mEditor.clearAllViews();
                break;

            case R.id.imgSave:
                saveImage();
                break;

            case R.id.imgClose:
                onBackPressed();
                break;
        }
    }

    @SuppressLint("MissingPermission")
    private void saveImage() {
        final String fileName = FileUtil.getInternalCacheDirectory(this, null)+"/"+"temp_"+System.currentTimeMillis()+".bmp";
        boolean hasStoragePermission =
                ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED;
        if (hasStoragePermission || isSdkHigherThan28()) {
            showLoading("Saving...");
            mSaveFileHelper.createFile(fileName, (fileCreated, filePath, error, uri) -> {
                if (fileCreated) {
                    SaveSettings saveSettings = new SaveSettings.Builder()
                            .setClearViewsEnabled(false)
                            .setTransparencyEnabled(true)
                            .build();

                    mEditor.saveAsFile(filePath, saveSettings, new Editor.OnSaveListener() {
//                        @Override
//                        public void onSuccess(@NonNull String imagePath) {
//                            mSaveFileHelper.notifyThatFileIsNowPubliclyAvailable(getContentResolver());
//                            hideLoading();
//                            showSnackbar("Image Saved Successfully");
//                            mSaveImageUri = uri;
//                            photoEditorView.getSource().setImageURI(mSaveImageUri);
//                        }

                        @Override
                        public void onSuccess(@NonNull Editor.ImageResult result) {
                            mSaveFileHelper.notifyThatFileIsNowPubliclyAvailable(getContentResolver());
                            hideLoading();
                            showSnackbar("Image Saved Successfully");
                            mSaveImageUri = uri;
                            photoEditorView.getSource().setImageURI(mSaveImageUri);
                        }

                        @Override
                        public void onFailure(@NonNull Exception exception) {
                            hideLoading();
                            showSnackbar("Failed to save Image");
                        }
                    });

                } else {
                    hideLoading();
                    showSnackbar(error);
                }
            });
        } else {
            requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
    }

    @Override
    public void onColorChanged(int colorCode) {
        mEditor.setShape(mShapeBuilder.withShapeColor(colorCode));
        PixUtils.getInstance().getPixBean().setColor(colorCode);
        mTxtCurrentTool.setText(R.string.label_brush);
    }

    @Override
    public void onOpacityChanged(int opacity) {
        mEditor.setShape(mShapeBuilder.withShapeOpacity(opacity));
        mTxtCurrentTool.setText(R.string.label_brush);
    }

    @Override
    public void onShapeSizeChanged(int shapeSize) {
        mEditor.setShape(mShapeBuilder.withShapeSize(shapeSize));
        mTxtCurrentTool.setText(R.string.label_brush);
    }

    @Override
    public void onShapePicked(ShapeType shapeType) {
        mEditor.setShape(mShapeBuilder.withShapeType(shapeType));
    }

    @Override
    public void onEmojiClick(String emojiUnicode) {
        mEditor.addEmoji(emojiUnicode);
        mTxtCurrentTool.setText(R.string.label_emoji);
    }

    @Override
    public void onStickerClick(Bitmap bitmap) {
        mEditor.addImage(bitmap);
        mTxtCurrentTool.setText(R.string.label_sticker);
    }

    @Override
    public void isPermissionGranted(boolean isGranted, String permission) {
        if (isGranted) {
            saveImage();
        }
    }

    private void showSaveDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getString(R.string.msg_save_image));
        builder.setPositiveButton("Save", (dialog, which) -> saveImage());
        builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
        builder.setNeutralButton("Discard", (dialog, which) -> finish());
        builder.create().show();

    }

    @Override
    public void onToolSelected(ToolType toolType) {
        switch (toolType) {
            case SHAPE:
                mEditor.setBrushDrawingMode(true);
                mShapeBuilder = new ShapeBuilder();
                mEditor.setShape(mShapeBuilder);
                mTxtCurrentTool.setText(R.string.label_shape);
                showBottomSheetDialogFragment(mShapeBSFragment);
                break;
            case TEXT:
                TextEditorDialogFragment textEditorDialogFragment = TextEditorDialogFragment.show(this);
                textEditorDialogFragment.setOnTextEditorListener((inputText, colorCode) -> {
                    final TextStyleBuilder styleBuilder = new TextStyleBuilder();
                    styleBuilder.withTextColor(colorCode);
                    styleBuilder.withTextFont(Typeface.createFromAsset(getAssets(), "fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf"));
                    mEditor.addText(inputText, styleBuilder);
                    mTxtCurrentTool.setText(R.string.label_text);
                });
                break;
            case ERASER:
                mEditor.brushEraser();
                mTxtCurrentTool.setText(R.string.label_eraser_mode);
                break;
            case EMOJI:
                showBottomSheetDialogFragment(mEmojiBSFragment);
                break;
            case STICKER:
                showBottomSheetDialogFragment(mStickerBSFragment);
                break;
        }
    }

    private void showBottomSheetDialogFragment(BottomSheetDialogFragment fragment) {
        if (fragment == null || fragment.isAdded()) {
            return;
        }
        fragment.show(getSupportFragmentManager(), fragment.getTag());
    }


    @Override
    public void onBackPressed() {
        if (!mEditor.isCacheEmpty()) {
            showSaveDialog();
        } else {
            super.onBackPressed();
        }
    }



    //****************************讯飞语音****cloud****************************
    // 语音听写对象
    private SpeechRecognizer mRecognize;
    // 语音听写UI
    private RecognizerDialog mRecognizeDialog;

    private ImageView speech;

    private void initSpeech(){
        soundPermissions();
        mRecognize = SpeechRecognizer.createRecognizer(this, mInitListener);

    }

    private void initSpeechLocal(){
        //        findViewById(R.id.speech).setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
////                initSpeechLocal();
////                ret = mIat.startListening(mRecognizerListener);
////                if (ret != ErrorCode.SUCCESS) {
////                    showTip("听写失败,错误码：" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
////                } else {
////                    showTip(getString(R.string.text_begin));
////                }
//            }
//        });

        // 初始化听写Dialog，如果只使用有UI听写功能，无需创建SpeechRecognizer
        // 使用UI听写功能，请将assets下文件拷贝到项目中
        mRecognizeDialog = new RecognizerDialog(this, mInitListener);
        setParamLocal();
    }

    private void initSpeechCloudDialog(){
        // 定义获取录音的动态权限


        // 初始化识别无UI识别对象，使用SpeechRecognizer对象，可根据回调消息自定义界面；
//        mRecognize = SpeechRecognizer.createRecognizer(this, mInitListener);


        findViewById(R.id.speech2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 设置参数
                resetParam();
                mRecognizeDialog.setListener(mRecognizeDialogListener);
                mRecognizeDialog.show();
            }
        });

//        findViewById(R.id.speech).setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
////                initSpeechLocal();
////                ret = mIat.startListening(mRecognizerListener);
////                if (ret != ErrorCode.SUCCESS) {
////                    showTip("听写失败,错误码：" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
////                } else {
////                    showTip(getString(R.string.text_begin));
////                }
//            }
//        });
//
//        findViewById(R.id.speech).setOnTouchListener(new View.OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                if(event.getAction() == MotionEvent.ACTION_UP){
//                    stop();
//                }
//                if(event.getAction() == MotionEvent.ACTION_DOWN){
//                    start();
//                }
//                return true;
//            }
//        });
    }

    private void start(){
        // 设置参数
//        resetParam();
        initSpeechLocal();
        mRecognize.startListening(mRecognizeListener);
    }

    private void stop(){
        mRecognize.stopListening();
    }

    // 定义录音的动态权限
    private void soundPermissions() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.RECORD_AUDIO}, 1);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 退出时释放连接
        mRecognize.cancel();
        mRecognize.destroy();
    }

    //初始化监听器
    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.d(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                Log.e(TAG, "初始化失败，错误码：" + code);
            }
        }
    };

    //参数设置
    public void resetParam() {
        // 清空参数
        mRecognize.setParameter(SpeechConstant.PARAMS, null);
        // 设置听写引擎。TYPE_LOCAL表示本地，TYPE_CLOUD表示云端，TYPE_MIX 表示混合
//        mRecognize.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        mRecognize.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 设置返回结果格式
        mRecognize.setParameter(SpeechConstant.RESULT_TYPE, "json");

        mRecognize.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
        mRecognize.setParameter(SpeechConstant.VAD_BOS,"4000");
        // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
        mRecognize.setParameter(SpeechConstant.VAD_EOS, "1000");
        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mRecognize.setParameter(SpeechConstant.ASR_PTT, "1");
        // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注：AUDIO_FORMAT参数语记需要更新版本才能生效
        mRecognize.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mRecognize.setParameter(SpeechConstant.ASR_AUDIO_PATH, context.getCacheDir()+"/msc/recognize.wav");
    }

    //听写监听器
    private RecognizerListener mRecognizeListener = new RecognizerListener() {

        @Override
        public void onBeginOfSpeech() {
            // 此回调表示：sdk内部录音机已经准备好了，用户可以开始语音输入
        }

        @Override
        public void onError(SpeechError error) {
            // 错误码：10118(您没有说话)，可能是录音机权限被禁，需要提示用户打开应用的录音权限。
            // 如果使用本地功能（语记）需要提示用户开启语记的录音权限。
        }

        @Override
        public void onEndOfSpeech() {
            // 此回调表示：检测到了语音的尾端点，已经进入识别过程，不再接受语音输入
        }

        @Override
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, results.getResultString());
            printResult(results);


        }

        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            Log.d(TAG, "返回音频数据："+data.length);
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
            // 若使用本地能力，会话id为null
            //	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //		Log.d(TAG, "session id =" + sid);
            //	}
        }
    };

    //听写UI监听器
    private RecognizerDialogListener mRecognizeDialogListener = new RecognizerDialogListener() {
        public void onResult(RecognizerResult results, boolean isLast) {
            printResult(results);
        }

        //识别回调错误
        public void onError(SpeechError error) {
        }
    };


    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());
        //设置画笔
        mEditor.setBrushDrawingMode(true);
        mShapeBuilder = new ShapeBuilder();
        mEditor.setShape(mShapeBuilder);
        //设置文字
        Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf");
        mEditor.addText(typeface, text, Color.WHITE);
    }

    /*****************************讯飞 local***************************************/

    private String mEngineType = SpeechConstant.TYPE_CLOUD;
    /**
     * 参数设置
     * https://www.xfyun.cn/doc/asr/offline_iat/Android-SDK.html#_3%E3%80%81%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE
     * @return
     */
    public void setParamLocal() {
        mEngineType = SpeechConstant.TYPE_LOCAL;
        // 清空参数
        mRecognize.setParameter(SpeechConstant.PARAMS, null);
//        String lag = mSharedPreferences.getString("iat_language_preference", "mandarin");
        // 设置引擎
        mRecognize.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 设置返回结果格式
        mRecognize.setParameter(SpeechConstant.RESULT_TYPE, "json");

        //mRecognize.setParameter(MscKeys.REQUEST_AUDIO_URL,"true");

        //	this.mTranslateEnable = mSharedPreferences.getBoolean( this.getString(R.string.pref_key_translate), false );
        if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
            // 设置本地识别资源
            mRecognize.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
        }
        // 在线听写支持多种小语种，若想了解请下载在线听写能力，参看其speechDemo 离线语音只支持中文
        mRecognize.setParameter(SpeechConstant.LANGUAGE, "zh_cn");

        // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
        mRecognize.setParameter(SpeechConstant.VAD_BOS, "4000");

        // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
        mRecognize.setParameter(SpeechConstant.VAD_EOS, "1000");

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mRecognize.setParameter(SpeechConstant.ASR_PTT, "1");

        // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        mRecognize.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mRecognize.setParameter(SpeechConstant.ASR_AUDIO_PATH,
                getExternalFilesDir("msc").getAbsolutePath() + "/iat.wav");
    }

    private String getResourcePath() {
        StringBuffer tempBuffer = new StringBuffer();
        //识别通用资源
        tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, "iat/common.jet"));
        tempBuffer.append(";");
        tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, "iat/sms_16k.jet"));
        //识别8k资源-使用8k的时候请解开注释
        return tempBuffer.toString();
    }

}
